home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 7 / rzsz0589.zip / ZM.C < prev    next >
C/C++ Source or Header  |  1989-05-25  |  18KB  |  902 lines

  1. /*
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    05-24-89  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * Entry point Functions:
  7.  *    zsbhdr(type, hdr) send binary header
  8.  *    zshhdr(type, hdr) send hex header
  9.  *    zgethdr(hdr, eflag) receive header - binary or hex
  10.  *    zsdata(buf, len, frameend) send data
  11.  *    zrdata(buf, len) receive data
  12.  *    stohdr(pos) store position data in Txhdr
  13.  *    long rclhdr(hdr) recover position offset from header
  14.  *
  15.  *    This version implements ZMODEM Run Length Encoding, Comparision,
  16.  *    and variable length headers.  These features were not funded
  17.  *    by the original Telenet development contract.  This software,
  18.  *    including these features, may be freely used for non
  19.  *    commercial and educational purposes.  This software may also
  20.  *    be freely used to support file transfer operations to or from
  21.  *    licensed Omen Technology products.  Contact Omen Technology
  22.  *    for licensing for other uses.  Any programs which use part or
  23.  *    all of this software must be provided in source form with this
  24.  *    notice intact except by written permission from Omen
  25.  *    Technology Incorporated.
  26.  *
  27.  *        Omen Technology Inc        FAX: 503-621-3745
  28.  *        Post Office Box 4681
  29.  *        Portland OR 97208
  30.  *
  31.  *    Previous versions of this program (not containing the extensions
  32.  *    listed above) remain in the public domain.
  33.  *
  34.  *    This code is made available in the hope it will be useful,
  35.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  36.  *    DAMAGES OF ANY KIND.
  37.  *
  38.  */
  39.  
  40. #ifndef CANFDX
  41. #include "zmodem.h"
  42. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  43. #endif
  44.  
  45. #ifndef UNSL
  46. #define UNSL
  47. #endif
  48.  
  49.  
  50. /* Globals used by ZMODEM functions */
  51. int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame */
  52. int Rxtype;        /* Type of header received */
  53. int Rxhlen;        /* Length of header received */
  54. int Rxcount;        /* Count of data bytes received */
  55. char Rxhdr[ZMAXHLEN];    /* Received header */
  56. char Txhdr[ZMAXHLEN];    /* Transmitted header */
  57. long Rxpos;        /* Received file position */
  58. long Txpos;        /* Transmitted file position */
  59. int Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  60. int Crc32t;        /* Controls 32 bit CRC being sent */
  61.             /* 1 == CRC32,  2 == CRC32 + RLE */
  62. int Crc32r;        /* Indicates/controls 32 bit CRC being received */
  63.             /* 0 == CRC16,  1 == CRC32,  2 == CRC32 + RLE */
  64. int Usevhdrs;        /* Use variable length headers */
  65. int Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  66. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  67. char *Altcan;        /* Alternate canit string */
  68.  
  69. static lastsent;    /* Last char we sent */
  70. static Not8bit;        /* Seven bits seen on header */
  71.  
  72. static char *frametypes[] = {
  73.     "No Response to Error Correction Request",    /* -4 */
  74.     "No Carrier Detect",        /* -3 */
  75.     "TIMEOUT",        /* -2 */
  76.     "ERROR",        /* -1 */
  77. #define FTOFFSET 4
  78.     "ZRQINIT",
  79.     "ZRINIT",
  80.     "ZSINIT",
  81.     "ZACK",
  82.     "ZFILE",
  83.     "ZSKIP",
  84.     "ZNAK",
  85.     "ZABORT",
  86.     "ZFIN",
  87.     "ZRPOS",
  88.     "ZDATA",
  89.     "ZEOF",
  90.     "ZFERR",
  91.     "ZCRC",
  92.     "ZCHALLENGE",
  93.     "ZCOMPL",
  94.     "ZCAN",
  95.     "ZFREECNT",
  96.     "ZCOMMAND",
  97.     "ZSTDERR",
  98.     "xxxxx"
  99. #define FRTYPES 22    /* Total number of frame types in this array */
  100.             /*  not including psuedo negative entries */
  101. };
  102.  
  103. static char badcrc[] = "Bad CRC";
  104.  
  105. /* Send ZMODEM binary header hdr of type type */
  106. zsbhdr(len, type, hdr)
  107. register char *hdr;
  108. {
  109.     register int n;
  110.     register unsigned short crc;
  111.  
  112. #ifndef DSZ
  113.     vfile("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  114.       frametypes[type+FTOFFSET], rclhdr(hdr));
  115. #endif
  116.     if (type == ZDATA)
  117.         for (n = Znulls; --n >=0; )
  118.             xsendline(0);
  119.  
  120.     xsendline(ZPAD); xsendline(ZDLE);
  121.  
  122.     switch (Crc32t=Txfcs32) {
  123.     case 2:
  124.         zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
  125.         flushmo();  break;
  126.     case 1:
  127.         zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32);  break;
  128.     default:
  129.         if (Usevhdrs) {
  130.             xsendline(ZVBIN);
  131.             zsendline(len);
  132.         }
  133.         else
  134.             xsendline(ZBIN);
  135.         zsendline(type);
  136.         crc = updcrc(type, 0);
  137.  
  138.         for (n=len; --n >= 0; ++hdr) {
  139.             zsendline(*hdr);
  140.             crc = updcrc((0377& *hdr), crc);
  141.         }
  142.         crc = updcrc(0,updcrc(0,crc));
  143.         zsendline(crc>>8);
  144.         zsendline(crc);
  145.     }
  146.     if (type != ZDATA)
  147.         flushmo();
  148. }
  149.  
  150.  
  151. /* Send ZMODEM binary header hdr of type type */
  152. zsbh32(len, hdr, type, flavour)
  153. register char *hdr;
  154. {
  155.     register int n;
  156.     register UNSL long crc;
  157.  
  158.     xsendline(flavour); 
  159.     if (Usevhdrs) 
  160.         zsendline(len);
  161.     zsendline(type);
  162.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  163.  
  164.     for (n=len; --n >= 0; ++hdr) {
  165.         crc = UPDC32((0377 & *hdr), crc);
  166.         zsendline(*hdr);
  167.     }
  168.     crc = ~crc;
  169.     for (n=4; --n >= 0;) {
  170.         zsendline((int)crc);
  171.         crc >>= 8;
  172.     }
  173. }
  174.  
  175. /* Send ZMODEM HEX header hdr of type type */
  176. zshhdr(len, type, hdr)
  177. register char *hdr;
  178. {
  179.     register int n;
  180.     register unsigned short crc;
  181.  
  182. #ifndef DSZ
  183.     vfile("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  184.       frametypes[type+FTOFFSET], rclhdr(hdr));
  185. #endif
  186.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE);
  187.     if (Usevhdrs) {
  188.         sendline(ZVHEX);
  189.         zputhex(len);
  190.     }
  191.     else
  192.         sendline(ZHEX);
  193.     zputhex(type);
  194.     Crc32t = 0;
  195.  
  196.     crc = updcrc(type, 0);
  197.     for (n=len; --n >= 0; ++hdr) {
  198.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  199.     }
  200.     crc = updcrc(0,updcrc(0,crc));
  201.     zputhex(crc>>8); zputhex(crc);
  202.  
  203.     /* Make it printable on remote machine */
  204.     sendline(015); sendline(0212);
  205.     /*
  206.      * Uncork the remote in case a fake XOFF has stopped data flow
  207.      */
  208.     if (type != ZFIN && type != ZACK)
  209.         sendline(021);
  210.     flushmo();
  211. }
  212.  
  213. /*
  214.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  215.  */
  216. static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  217. zsdata(buf, length, frameend)
  218. register char *buf;
  219. {
  220.     register unsigned short crc;
  221.  
  222. #ifndef DSZ
  223.     vfile("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
  224. #endif
  225.     switch (Crc32t) {
  226.     case 1:
  227.         zsda32(buf, length, frameend);  break;
  228.     case 2:
  229.         zsdar32(buf, length, frameend);  break;
  230.     default:
  231.         crc = 0;
  232.         for (;--length >= 0; ++buf) {
  233.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  234.         }
  235.         xsendline(ZDLE); xsendline(frameend);
  236.         crc = updcrc(frameend, crc);
  237.  
  238.         crc = updcrc(0,updcrc(0,crc));
  239.         zsendline(crc>>8); zsendline(crc);
  240.     }
  241.     if (frameend == ZCRCW) {
  242.         xsendline(XON);  flushmo();
  243.     }
  244. }
  245.  
  246. zsda32(buf, length, frameend)
  247. register char *buf;
  248. {
  249.     register int c;
  250.     register UNSL long crc;
  251.  
  252.     crc = 0xFFFFFFFFL;
  253.     for (;--length >= 0; ++buf) {
  254.         c = *buf & 0377;
  255.         if (c & 0140)
  256.             xsendline(lastsent = c);
  257.         else
  258.             zsendline(c);
  259.         crc = UPDC32(c, crc);
  260.     }
  261.     xsendline(ZDLE); xsendline(frameend);
  262.     crc = UPDC32(frameend, crc);
  263.  
  264.     crc = ~crc;
  265.     for (c=4; --c >= 0;) {
  266.         zsendline((int)crc);  crc >>= 8;
  267.     }
  268. }
  269.  
  270. /*
  271.  * Receive array buf of max length with ending ZDLE sequence
  272.  *  and CRC.  Returns the ending character or error code.
  273.  *  NB: On errors may store length+1 bytes!
  274.  */
  275. zrdata(buf, length)
  276. register char *buf;
  277. {
  278.     register int c;
  279.     register unsigned short crc;
  280.     register char *end;
  281.     register int d;
  282.  
  283.     switch (Crc32r) {
  284.     case 1:
  285.         return zrdat32(buf, length);
  286.     case 2:
  287.         return zrdatr32(buf, length);
  288.     }
  289.  
  290.     crc = Rxcount = 0;  end = buf + length;
  291.     while (buf <= end) {
  292.         if ((c = zdlread()) & ~0377) {
  293. crcfoo:
  294.             switch (c) {
  295.             case GOTCRCE:
  296.             case GOTCRCG:
  297.             case GOTCRCQ:
  298.             case GOTCRCW:
  299.                 crc = updcrc((d=c)&0377, crc);
  300.                 if ((c = zdlread()) & ~0377)
  301.                     goto crcfoo;
  302.                 crc = updcrc(c, crc);
  303.                 if ((c = zdlread()) & ~0377)
  304.                     goto crcfoo;
  305.                 crc = updcrc(c, crc);
  306.                 if (crc & 0xFFFF) {
  307.                     zperr(badcrc);
  308.                     return ERROR;
  309.                 }
  310.                 Rxcount = length - (end - buf);
  311. #ifndef DSZ
  312.                 vfile("zrdata: %d  %s", Rxcount,
  313.                  Zendnames[d-GOTCRCE&3]);
  314. #endif
  315.                 return d;
  316.             case GOTCAN:
  317.                 zperr("Sender Canceled");
  318.                 return ZCAN;
  319.             case TIMEOUT:
  320.                 zperr("TIMEOUT");
  321.                 return c;
  322.             default:
  323.                 garbitch(); return c;
  324.             }
  325.         }
  326.         *buf++ = c;
  327.         crc = updcrc(c, crc);
  328.     }
  329. #ifdef DSZ
  330.     garbitch(); 
  331. #else
  332.     zperr("Data subpacket too long");
  333. #endif
  334.     return ERROR;
  335. }
  336.  
  337. zrdat32(buf, length)
  338. register char *buf;
  339. {
  340.     register int c;
  341.     register UNSL long crc;
  342.     register char *end;
  343.     register int d;
  344.  
  345.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  346.     while (buf <= end) {
  347.         if ((c = zdlread()) & ~0377) {
  348. crcfoo:
  349.             switch (c) {
  350.             case GOTCRCE:
  351.             case GOTCRCG:
  352.             case GOTCRCQ:
  353.             case GOTCRCW:
  354.                 d = c;  c &= 0377;
  355.                 crc = UPDC32(c, crc);
  356.                 if ((c = zdlread()) & ~0377)
  357.                     goto crcfoo;
  358.                 crc = UPDC32(c, crc);
  359.                 if ((c = zdlread()) & ~0377)
  360.                     goto crcfoo;
  361.                 crc = UPDC32(c, crc);
  362.                 if ((c = zdlread()) & ~0377)
  363.                     goto crcfoo;
  364.                 crc = UPDC32(c, crc);
  365.                 if ((c = zdlread()) & ~0377)
  366.                     goto crcfoo;
  367.                 crc = UPDC32(c, crc);
  368.                 if (crc != 0xDEBB20E3) {
  369.                     zperr(badcrc);
  370.                     return ERROR;
  371.                 }
  372.                 Rxcount = length - (end - buf);
  373. #ifndef DSZ
  374.                 vfile("zrdat32: %d %s", Rxcount,
  375.                  Zendnames[d-GOTCRCE&3]);
  376. #endif
  377.                 return d;
  378.             case GOTCAN:
  379.                 zperr("Sender Canceled");
  380.                 return ZCAN;
  381.             case TIMEOUT:
  382.                 zperr("TIMEOUT");
  383.                 return c;
  384.             default:
  385.                 garbitch(); return c;
  386.             }
  387.         }
  388.         *buf++ = c;
  389.         crc = UPDC32(c, crc);
  390.     }
  391.     zperr("Data subpacket too long");
  392.     return ERROR;
  393. }
  394.  
  395. garbitch()
  396. {
  397.     zperr("Garbled data subpacket");
  398. }
  399.  
  400. /*
  401.  * Read a ZMODEM header to hdr, either binary or hex.
  402.  *  eflag controls local display of non zmodem characters:
  403.  *    0:  no display
  404.  *    1:  display printing characters only
  405.  *    2:  display all non ZMODEM characters
  406.  *
  407.  *   Set Rxhlen to size of header (default 4) (valid iff good hdr)
  408.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  409.  *   Otherwise return negative on error.
  410.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  411.  */
  412. zgethdr(hdr, eflag)
  413. char *hdr;
  414. {
  415.     register int c, n, cancount;
  416.  
  417.     n = Zrwindow + Effbaud;        /* Max bytes before start of frame */
  418.     Rxframeind = Rxtype = 0;
  419.  
  420. startover:
  421.     cancount = 5;
  422. again:
  423.     /* Return immediate ERROR if ZCRCW sequence seen */
  424.     switch (c = readline(Rxtimeout)) {
  425.     case RCDO:
  426.     case TIMEOUT:
  427.         goto fifi;
  428.     case CAN:
  429. gotcan:
  430.         if (--cancount <= 0) {
  431.             c = ZCAN; goto fifi;
  432.         }
  433.         switch (c = readline(1)) {
  434.         case TIMEOUT:
  435.             goto again;
  436.         case ZCRCW:
  437.             switch (readline(1)) {
  438.             case TIMEOUT:
  439.                 c = ERROR; goto fifi;
  440.             case RCDO:
  441.                 goto fifi;
  442.             default:
  443.                 goto agn2;
  444.             }
  445.         case RCDO:
  446.             goto fifi;
  447.         default:
  448.             break;
  449.         case CAN:
  450.             if (--cancount <= 0) {
  451.                 c = ZCAN; goto fifi;
  452.             }
  453.             goto again;
  454.         }
  455.     /* **** FALL THRU TO **** */
  456.     default:
  457. agn2:
  458.         if ( --n == 0) {
  459.             c = GCOUNT;  goto fifi;
  460.         }
  461.         if (eflag && ((c &= 0177) & 0140))
  462.             bttyout(c);
  463.         else if (eflag > 1)
  464.             bttyout(c);
  465. #ifdef UNIX
  466.         fflush(stderr);
  467. #endif
  468.         goto startover;
  469.     case ZPAD|0200:        /* This is what we want. */
  470.         Not8bit = c;
  471.     case ZPAD:        /* This is what we want. */
  472.         break;
  473.     }
  474.     cancount = 5;
  475. splat:
  476.     switch (c = noxrd7()) {
  477.     case ZPAD:
  478.         goto splat;
  479.     case RCDO:
  480.     case TIMEOUT:
  481.         goto fifi;
  482.     default:
  483.         goto agn2;
  484.     case ZDLE:        /* This is what we want. */
  485.         break;
  486.     }
  487.  
  488.  
  489.     Rxhlen = 4;        /* Set default length */
  490.     Rxframeind = c = noxrd7();
  491.     switch (c) {
  492.     case ZVBIN32:
  493.         if ((Rxhlen = c = zdlread()) < 0)
  494.             goto fifi;
  495.         if (c > ZMAXHLEN)
  496.             goto agn2;
  497.         Crc32r = 1;  c = zrbhd32(hdr); break;
  498.     case ZBIN32:
  499.         if (Usevhdrs)
  500.             goto agn2;
  501.         Crc32r = 1;  c = zrbhd32(hdr); break;
  502.     case ZVBINR32:
  503.         if ((Rxhlen = c = zdlread()) < 0)
  504.             goto fifi;
  505.         if (c > ZMAXHLEN)
  506.             goto agn2;
  507.         Crc32r = 2;  c = zrbhd32(hdr); break;
  508.     case ZBINR32:
  509.         if (Usevhdrs)
  510.             goto agn2;
  511.         Crc32r = 2;  c = zrbhd32(hdr); break;
  512.     case RCDO:
  513.     case TIMEOUT:
  514.         goto fifi;
  515.     case ZVBIN:
  516.         if ((Rxhlen = c = zdlread()) < 0)
  517.             goto fifi;
  518.         if (c > ZMAXHLEN)
  519.             goto agn2;
  520.         Crc32r = 0;  c = zrbhdr(hdr); break;
  521.     case ZBIN:
  522.         if (Usevhdrs)
  523.             goto agn2;
  524.         Crc32r = 0;  c = zrbhdr(hdr); break;
  525.     case ZVHEX:
  526.         if ((Rxhlen = c = zgethex()) < 0)
  527.             goto fifi;
  528.         if (c > ZMAXHLEN)
  529.             goto agn2;
  530.         Crc32r = 0;  c = zrhhdr(hdr); break;
  531.     case ZHEX:
  532.         if (Usevhdrs)
  533.             goto agn2;
  534.         Crc32r = 0;  c = zrhhdr(hdr); break;
  535.     case CAN:
  536.         goto gotcan;
  537.     default:
  538.         goto agn2;
  539.     }
  540.     Rxpos = hdr[ZP3] & 0377;
  541.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  542.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  543.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  544. fifi:
  545.     switch (c) {
  546.     case GOTCAN:
  547.         c = ZCAN;
  548.     /* **** FALL THRU TO **** */
  549.     case ZNAK:
  550.     case ZCAN:
  551.     case ERROR:
  552.     case TIMEOUT:
  553.     case RCDO:
  554.     case GCOUNT:
  555.         zperr("Got %s", frametypes[c+FTOFFSET]);
  556.     /* **** FALL THRU TO **** */
  557. #ifndef DSZ
  558.     default:
  559.         if (c >= -4 && c <= FRTYPES)
  560.             vfile("zgethdr: %c %d %s %lx", Rxframeind, Rxhlen,
  561.               frametypes[c+FTOFFSET], Rxpos);
  562.         else
  563.             vfile("zgethdr: %c %d %lx", Rxframeind, c, Rxpos);
  564. #endif
  565.     }
  566.     /* Use variable length headers if we got one */
  567.     if (c >= 0 && c <= FRTYPES && Rxframeind & 040)
  568.         Usevhdrs = 1;
  569.     return c;
  570. }
  571.  
  572. /* Receive a binary style header (type and position) */
  573. zrbhdr(hdr)
  574. register char *hdr;
  575. {
  576.     register int c, n;
  577.     register unsigned short crc;
  578.  
  579.     if ((c = zdlread()) & ~0377)
  580.         return c;
  581.     Rxtype = c;
  582.     crc = updcrc(c, 0);
  583.  
  584.     for (n=Rxhlen; --n >= 0; ++hdr) {
  585.         if ((c = zdlread()) & ~0377)
  586.             return c;
  587.         crc = updcrc(c, crc);
  588.         *hdr = c;
  589.     }
  590.     if ((c = zdlread()) & ~0377)
  591.         return c;
  592.     crc = updcrc(c, crc);
  593.     if ((c = zdlread()) & ~0377)
  594.         return c;
  595.     crc = updcrc(c, crc);
  596.     if (crc & 0xFFFF) {
  597.         zperr(badcrc);
  598.         return ERROR;
  599.     }
  600. #ifdef ZMODEM
  601.     Protocol = ZMODEM;
  602. #endif
  603.     Zmodem = 1;
  604.     return Rxtype;
  605. }
  606.  
  607. /* Receive a binary style header (type and position) with 32 bit FCS */
  608. zrbhd32(hdr)
  609. register char *hdr;
  610. {
  611.     register int c, n;
  612.     register UNSL long crc;
  613.  
  614.     if ((c = zdlread()) & ~0377)
  615.         return c;
  616.     Rxtype = c;
  617.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  618. #ifdef DEBUGZ
  619.     vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  620. #endif
  621.  
  622.     for (n=Rxhlen; --n >= 0; ++hdr) {
  623.         if ((c = zdlread()) & ~0377)
  624.             return c;
  625.         crc = UPDC32(c, crc);
  626.         *hdr = c;
  627. #ifdef DEBUGZ
  628.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  629. #endif
  630.     }
  631.     for (n=4; --n >= 0;) {
  632.         if ((c = zdlread()) & ~0377)
  633.             return c;
  634.         crc = UPDC32(c, crc);
  635. #ifdef DEBUGZ
  636.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  637. #endif
  638.     }
  639.     if (crc != 0xDEBB20E3) {
  640.         zperr(badcrc);
  641.         return ERROR;
  642.     }
  643. #ifdef ZMODEM
  644.     Protocol = ZMODEM;
  645. #endif
  646.     Zmodem = 1;
  647.     return Rxtype;
  648. }
  649.  
  650.  
  651. /* Receive a hex style header (type and position) */
  652. zrhhdr(hdr)
  653. char *hdr;
  654. {
  655.     register int c;
  656.     register unsigned short crc;
  657.     register int n;
  658.  
  659.     if ((c = zgethex()) < 0)
  660.         return c;
  661.     Rxtype = c;
  662.     crc = updcrc(c, 0);
  663.  
  664.     for (n=Rxhlen; --n >= 0; ++hdr) {
  665.         if ((c = zgethex()) < 0)
  666.             return c;
  667.         crc = updcrc(c, crc);
  668.         *hdr = c;
  669.     }
  670.     if ((c = zgethex()) < 0)
  671.         return c;
  672.     crc = updcrc(c, crc);
  673.     if ((c = zgethex()) < 0)
  674.         return c;
  675.     crc = updcrc(c, crc);
  676.     if (crc & 0xFFFF) {
  677.         zperr(badcrc); return ERROR;
  678.     }
  679.     switch ( c = readline(1)) {
  680.     case 0215:
  681.         Not8bit = c;
  682.         /* **** FALL THRU TO **** */
  683.     case 015:
  684.          /* Throw away possible cr/lf */
  685.         switch (c = readline(1)) {
  686.         case 012:
  687.             Not8bit |= c;
  688.         }
  689.     }
  690. #ifdef ZMODEM
  691.     Protocol = ZMODEM;
  692. #endif
  693.     Zmodem = 1; return Rxtype;
  694. }
  695.  
  696. /* Send a byte as two hex digits */
  697. zputhex(c)
  698. register int c;
  699. {
  700.     static char    digits[]    = "0123456789abcdef";
  701.  
  702. #ifdef DEBUGZ
  703.     if (Verbose>8)
  704.         vfile("zputhex: %02X", c);
  705. #endif
  706.     sendline(digits[(c&0xF0)>>4]);
  707.     sendline(digits[(c)&0xF]);
  708. }
  709.  
  710. /*
  711.  * Send character c with ZMODEM escape sequence encoding.
  712.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  713.  */
  714. zsendline(c)
  715. {
  716.  
  717.     /* Quick check for non control characters */
  718.     if (c & 0140)
  719.         xsendline(lastsent = c);
  720.     else {
  721.         switch (c &= 0377) {
  722.         case ZDLE:
  723.             xsendline(ZDLE);
  724.             xsendline (lastsent = (c ^= 0100));
  725.             break;
  726.         case 015:
  727.         case 0215:
  728.             if (!Zctlesc && (lastsent & 0177) != '@')
  729.                 goto sendit;
  730.         /* **** FALL THRU TO **** */
  731.         case 020:
  732.         case 021:
  733.         case 023:
  734.         case 0220:
  735.         case 0221:
  736.         case 0223:
  737.             xsendline(ZDLE);
  738.             c ^= 0100;
  739.     sendit:
  740.             xsendline(lastsent = c);
  741.             break;
  742.         default:
  743.             if (Zctlesc && ! (c & 0140)) {
  744.                 xsendline(ZDLE);
  745.                 c ^= 0100;
  746.             }
  747.             xsendline(lastsent = c);
  748.         }
  749.     }
  750. }
  751.  
  752. /* Decode two lower case hex digits into an 8 bit byte value */
  753. zgethex()
  754. {
  755.     register int c;
  756.  
  757.     c = zgeth1();
  758. #ifdef DEBUGZ
  759.     if (Verbose>8)
  760.         vfile("zgethex: %02X", c);
  761. #endif
  762.     return c;
  763. }
  764. zgeth1()
  765. {
  766.     register int c, n;
  767.  
  768.     if ((c = noxrd7()) < 0)
  769.         return c;
  770.     n = c - '0';
  771.     if (n > 9)
  772.         n -= ('a' - ':');
  773.     if (n & ~0xF)
  774.         return ERROR;
  775.     if ((c = noxrd7()) < 0)
  776.         return c;
  777.     c -= '0';
  778.     if (c > 9)
  779.         c -= ('a' - ':');
  780.     if (c & ~0xF)
  781.         return ERROR;
  782.     c += (n<<4);
  783.     return c;
  784. }
  785.  
  786. /*
  787.  * Read a byte, checking for ZMODEM escape encoding
  788.  *  including CAN*5 which represents a quick abort
  789.  */
  790. zdlread()
  791. {
  792.     register int c;
  793.  
  794. again:
  795.     /* Quick check for non control characters */
  796.     if ((c = readline(Rxtimeout)) & 0140)
  797.         return c;
  798.     switch (c) {
  799.     case ZDLE:
  800.         break;
  801.     case 023:
  802.     case 0223:
  803.     case 021:
  804.     case 0221:
  805.         goto again;
  806.     default:
  807.         if (Zctlesc && !(c & 0140)) {
  808.             goto again;
  809.         }
  810.         return c;
  811.     }
  812. again2:
  813.     if ((c = readline(Rxtimeout)) < 0)
  814.         return c;
  815.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  816.         return c;
  817.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  818.         return c;
  819.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  820.         return c;
  821.     switch (c) {
  822.     case CAN:
  823.         return GOTCAN;
  824.     case ZCRCE:
  825.     case ZCRCG:
  826.     case ZCRCQ:
  827.     case ZCRCW:
  828.         return (c | GOTOR);
  829.     case ZRUB0:
  830.         return 0177;
  831.     case ZRUB1:
  832.         return 0377;
  833.     case 023:
  834.     case 0223:
  835.     case 021:
  836.     case 0221:
  837.         goto again2;
  838.     default:
  839.         if (Zctlesc && ! (c & 0140)) {
  840.             goto again2;
  841.         }
  842.         if ((c & 0140) ==  0100)
  843.             return (c ^ 0100);
  844.         break;
  845.     }
  846.     if (Verbose>1)
  847.         zperr("Bad escape sequence %x", c);
  848.     return ERROR;
  849. }
  850.  
  851. /*
  852.  * Read a character from the modem line with timeout.
  853.  *  Eat parity, XON and XOFF characters.
  854.  */
  855. noxrd7()
  856. {
  857.     register int c;
  858.  
  859.     for (;;) {
  860.         if ((c = readline(Rxtimeout)) < 0)
  861.             return c;
  862.         switch (c &= 0177) {
  863.         case XON:
  864.         case XOFF:
  865.             continue;
  866.         default:
  867.             if (Zctlesc && !(c & 0140))
  868.                 continue;
  869.         case '\r':
  870.         case '\n':
  871.         case ZDLE:
  872.             return c;
  873.         }
  874.     }
  875. }
  876.  
  877. /* Store long integer pos in Txhdr */
  878. stohdr(pos)
  879. long pos;
  880. {
  881.     Txhdr[ZP0] = pos;
  882.     Txhdr[ZP1] = pos>>8;
  883.     Txhdr[ZP2] = pos>>16;
  884.     Txhdr[ZP3] = pos>>24;
  885. }
  886.  
  887. /* Recover a long integer from a header */
  888. long
  889. rclhdr(hdr)
  890. register char *hdr;
  891. {
  892.     register long l;
  893.  
  894.     l = (hdr[ZP3] & 0377);
  895.     l = (l << 8) | (hdr[ZP2] & 0377);
  896.     l = (l << 8) | (hdr[ZP1] & 0377);
  897.     l = (l << 8) | (hdr[ZP0] & 0377);
  898.     return l;
  899. }
  900.  
  901. /* End of zm.c */
  902.